RAG 비법노트 심화편 — 딥다이브 학습 노트
학습 로드맵
EP1 LLM 증강질의 복습
│ (모델 튜닝 한계 → 프롬프트 튜닝 대안)
▼
EP2 임베딩 불일치 보완
│ (인코더 정체 → 쿼리-데이터 시멘틱 갭 → 하이브리드 검색)
▼
EP3 리랭커로 품질 끌어올리기
│ (크로스 인코더 → LLM 기반 리랭커)
▼
EP4 컨텍스트 압축
│ (어텐션 희석 → Stuff/MapReduce/MapRefine/ClusterMapRefine)
▼
EP5 RAG와 프롬프트
│ (입력 편향 + 출력 편향 → 어텐션 희석 → 토큰 임베딩 차원)
▼
EP6 RAPTOR의 허실
│ (계층적 클러스터링 → 차원 축소 파괴 / 컨텍스트 혼합 / 유사 시멘틱)
▼
EP7 RAG 시스템 평가
│ (정확성·관련성·이행성·안정성 → LLM-as-Judge → 테스트셋 생성)
▼
EP8 RAG 시스템 튜닝
(청크 튜닝 → 벡터 검색 튜닝 → 비임베딩 강화 → 부분 요소 교체)
선수 지식 체크리스트
- [ ] 트랜스포머 아키텍처 (어텐션, 멀티헤드, FFN)
- [ ] 인코더 vs 디코더 차이
- [ ] 임베딩·코사인 유사도 개념
- [ ] 벡터 DB 기본 사용법 (Chroma, FAISS 등)
- [ ] RAG 기본 파이프라인 (→ 기본편 EP1~EP9 참고)
추천 학습 순서
- EP1~EP2: 기본편 복습 + 임베딩 한계 이해
- EP3~EP4: 검색 품질 향상 기법 (리랭커 → 컨텍스트 압축)
- EP5: 프롬프트 엔지니어링의 원리 (어텐션 편향)
- EP6: RAPTOR 비판적 분석
- EP7~EP8: 평가·튜닝 사이클
EP1. LLM 증강질의 복습 — 모델 튜닝 vs 프롬프트 튜닝
강의 핵심 요약
LLM 튜닝에는 모델 튜닝(파라미터 직접 수정)과 프롬프트 튜닝(입력으로 편향 유도) 두 가지만 존재한다. 모델 튜닝은 데이터 부족, 비용, 균형 파괴 문제로 실무에서 극히 어렵고, 대부분의 RAG 시스템은 프롬프트 튜닝(= 입력 편향)으로 해결한다. Agentic AI(Qwen, Anthropic MCP)는 외부 도구 연동의 새로운 패러다임이다.
딥다이브
모델 튜닝이 어려운 이유
| 문제 | 상세 |
|---|---|
| 데이터 요구량 | 7B 모델 유의미 튜닝에 150~200만 completion 필요. 기업 도메인 데이터는 보통 4만 개 수준 |
| 비용 | 7B 모델 학습에 GPU 5천만원+ 필요 (추론은 RTX 4080, ~200만원으로 충분) |
| 균형 파괴 | 도메인 특화 학습 시 기존 상식 추론이 망가짐 (catastrophic forgetting) |
| 학습 비용 비율 | 학습 비용 ≈ 추론 비용 × 10 |
LoRA/QLoRA 레이어별 튜닝 전략
LLM의 학습 가능 레이어는 어텐션 레이어와 FFN(MLP) 레이어 두 곳이다:
- 어텐션 레이어: 건드리면 위험 → LoRA/QLoRA에서도 보통 회피
- FFN/MLP 레이어: 비교적 안전하게 미세 조정 가능
- 임베딩 모델: 모델 자체는 건드리지 않고, 하위에 로지스틱 회귀층이나 MLP를 추가
# LoRA 설정 예시 — FFN 레이어만 타겟
from peft import LoraConfig
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["gate_proj", "up_proj", "down_proj"], # FFN만
lora_dropout=0.05,
task_type="CAUSAL_LM"
)
⚠️ 최신 업데이트: 2025~2026 벤치마크에 따르면 QLoRA는 full fine-tuning 대비 80~90% 품질을 달성하며, LoRA는 0.1~1% 파라미터만 학습해도 거의 동등한 결과를 보인다. 단, LaRA 벤치마크(2025)는 RAG vs Fine-tuning에서 "만능 해법은 없다"고 결론 — 태스크 유형별 선택이 핵심이다.
Agentic AI
- Qwen 3.5: 알리바바의 오픈소스 모델. 외부 도구 연동(tool calling)에 특화하여 학습
- Anthropic Claude + MCP: 유료 모델 중 tool picking 정확도가 가장 높음
- 핵심: 모델 자체를 튜닝하지 않고, 프롬프트 + 도구 명세로 외부 시스템과 연동
실무 적용
# RAG에서 모델 튜닝 대신 프롬프트 튜닝으로 해결하는 패턴
system_prompt = """당신은 {domain} 전문가입니다.
아래 컨텍스트만을 기반으로 답변하세요.
컨텍스트에 없는 내용은 "정보 없음"이라 답하세요.
[컨텍스트]
{retrieved_chunks}
"""
# → 모델 파라미터를 건드리지 않고 입력 편향만으로 도메인 특화
핵심 체크포인트
- ✅ 모델 튜닝은 데이터 100만+ 필요, 비용·균형 파괴 리스크 → 실무에서 프롬프트 튜닝이 현실적
- ✅ LoRA/QLoRA 사용 시에도 어텐션 레이어는 회피하고 FFN만 타겟
- ✅ Agentic AI는 모델 튜닝 없이 프롬프트 + 도구 명세로 외부 연동
EP2. 임베딩 불일치 보완 — 인코더의 정체와 시멘틱 갭
강의 핵심 요약
임베딩이 불일치하는 근본 원인은 두 가지: (1) 인코더 모델 자체가 구식 어텐션 기반(BERT)으로 정체되어 있고, (2) 쿼리(의도 기반)와 데이터(팩트 기반)의 시멘틱 구조가 태생적으로 다르다. 보완 방법으로 BM25/Elasticsearch 기반 하이브리드 검색을 병행한다.
딥다이브
인코더 모델 정체의 구조적 원인
디코더 (GPT, Claude, Gemini) 인코더 (BERT 계열)
───────────────────────── ──────────────────
• Group Attention • 2018년 이후 어텐션 발전 없음
• MoE (Mixture of Experts) • 대부분 BERT가 시드 모델
• Flash Attention • 투자·연구 관심 없음
• 계속 진화 중 • 사실상 버려진 아키텍처
- 인코더: 입력 → 어텐션 1회 → 결론 (폐쇄망). 빠르지만 출력 편향 없음
- 디코더: 입력 → 토큰 생성 반복 (어텐션 매회 재계산). 느리지만 프롬프트 통제 가능
- 결과: 인코더 기반 임베딩 = 구식 어텐션 → 허접한 시멘틱 표현
⚠️ 최신 업데이트: 2025~2026 MTEB 리더보드 상위 모델 — Cohere embed-v4 (65.2), OpenAI text-embedding-3-large (64.6), Voyage AI voyage-3.5 시리즈. Google은 gemini-embedding-001(Matryoshka Representation Learning 적용)과 EmbeddingGemma(308M 파라미터, 온디바이스 특화)를 발표했다. 그러나 이들도 여전히 인코더 기반이며 디코더 대비 어텐션 진화 폭은 제한적이다.
쿼리-데이터 시멘틱 불일치
| 구분 | 쿼리 (사용자 질의) | 데이터 (청크) |
|---|---|---|
| 성격 | 의도 + 컨텍스트 + 감정 복합 | 팩트 중심, 단순 서술 |
| 시멘틱 | 복합적 의도 기반 임베딩 | 사실 기반 임베딩 |
| 예시 | "이번 분기에 삼성전자가 괜찮은 거야?" | "삼성전자 2분기 영업이익 14조원" |
| 결과 | 두 임베딩의 코사인 유사도가 낮음 |
BM25 하이브리드 검색
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# 벡터 검색 + BM25 키워드 검색 앙상블
ensemble = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.5, 0.5] # 시멘틱 50% + 키워드 50%
)
- BM25: 형태소 분석 → 토큰 인덱스 → TF-IDF 기반 토큰 카운트 비교
- Elasticsearch/Solr 계열의 풀텍스트 인덱싱도 동일 원리
- 임베딩이 못 잡는 키워드 매칭을 보완
실무 적용
# 정규화 후 코사인 유사도 계산 (임베딩 원리)
import numpy as np
def cosine_similarity(a, b):
# 정규화: 각 원소 제곱 합의 루트로 나눔
a_norm = a / np.linalg.norm(a)
b_norm = b / np.linalg.norm(b)
return np.dot(a_norm, b_norm)
# 임베딩 모델 출력은 비정규화 상태 → 벡터 DB 저장 전 정규화 필수
핵심 체크포인트
- ✅ 인코더 기반 임베딩 모델은 BERT 시대에서 어텐션이 멈춰 있어 시멘틱 표현이 제한적
- ✅ 쿼리(의도)와 데이터(팩트)는 태생적으로 시멘틱 구조가 달라 임베딩 불일치 발생
- ✅ BM25 하이브리드 검색으로 키워드 매칭을 보완 — 저비용 고효과
EP3. RAG 품질을 끌어올리는 리랭커
강의 핵심 요약
벡터 DB 검색 결과의 유사도 점수를 신뢰할 수 없으므로, N개 결과를 리랭커로 재정렬하여 상위 X개만 LLM에 전달한다. 크로스 인코더 리랭커는 빠르지만 구식 어텐션의 한계를 공유하며, 디코더(LLM) 기반 리랭커는 프롬프트 통제·도메인 지식 주입·중복 제거가 가능하다.
딥다이브
리랭커 기본 흐름
사용자 질의 → 임베딩 → 벡터 DB 검색 (N개)
↓
리랭커 재정렬 (N → X개)
↓
시스템 프롬프트 + X개 컨텍스트 + 질의 → LLM → 답변
크로스 인코더 리랭커
- 학습 방법: BERT를
[CLS] query [SEP] passage형태로 학습 - 학습 데이터: MS MARCO Passage Ranking (크로스 인코더 90%가 이 데이터 기반)
- 구조: 쿼리 1개 + 정답 1~2개 + 오답 다수 → 유사도 점수(0~1) 출력 학습
- 장점: 인코더이므로 어텐션 1회 → 빠른 속도
- 한계:
- N개 문서에 대해 N번 개별 호출 (쿼리+문서 쌍마다 1회)
- 프롬프트 통제 불가 — 모델 학습 성향 그대로
- 도메인 지식 주입 불가
- 중복 문서 판별 불가
LLM 기반 리랭커 (디코더)
| 항목 | 크로스 인코더 | LLM 리랭커 |
|---|---|---|
| 호출 횟수 | N번 (문서당 1회) | 1번 (전체 문서 listwise) |
| 프롬프트 통제 | 불가 | "최신 소스 우선" 등 자연어 지시 가능 |
| 도메인 지식 | 학습 데이터 한정 | 프롬프트로 도메인 규칙 주입 가능 |
| 중복 판별 | 불가 | 전체 문서를 한 번에 보므로 가능 |
| 속도 | 빠름 (인코더) | 느림 (디코더) |
| 비용 | 저비용 | 고비용 |
⚠️ 최신 업데이트: 2025~2026 권장 아키텍처는 2-stage 하이브리드 — (1) 크로스 인코더로 top-20 축소 (5~10ms), (2) LLM listwise 리랭킹으로 top-10 최종 정렬 (200~500ms). ZeroEntropy의 zerank-1은 NDCG@10에서 +28% 향상을 보이며, LLM 정확도의 95%를 3x 빠른 속도로 달성한다.
실무 적용
# 크로스 인코더 리랭커 사용 예시
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
# N개 검색 결과를 재정렬
pairs = [(query, doc.page_content) for doc in search_results]
scores = reranker.predict(pairs)
# 상위 X개만 선택
top_x = sorted(zip(scores, search_results), reverse=True)[:5]
# LLM 기반 listwise 리랭커 (프롬프트 통제 가능)
rerank_prompt = """다음 문서들을 질문과의 관련성 순으로 정렬하세요.
중복 문서는 하나만 남기세요.
최신 정보를 우선하세요.
질문: {query}
문서들: {documents}
JSON 형식으로 정렬된 문서 ID 목록을 반환하세요."""
핵심 체크포인트
- ✅ 벡터 DB 유사도 점수는 신뢰할 수 없음 → 리랭커로 재정렬 필수
- ✅ 크로스 인코더는 빠르지만 N번 호출·프롬프트 통제 불가 — 1차 필터용
- ✅ LLM 리랭커는 느리지만 listwise 1회 호출·프롬프트 통제·중복 제거 가능 — 최종 정렬용
EP4. RAG 결과를 프롬프트에 '잘' 넣기 — 컨텍스트 압축
강의 핵심 요약
검색 결과를 그대로 프롬프트에 넣으면 어텐션 희석으로 답변 품질이 떨어진다. LLM에게 요약을 시키면, LLM이 편향을 가장 잘 일으킬 형태로 압축하므로 합리적이다. 요약 기법: Stuff, MapReduce, MapRefine, ClusterMapRefine.
딥다이브
왜 LLM이 요약해야 하는가
핵심 논리: 편향을 일으키는 당사자(LLM)가 편향에 최적인 형태로 요약하는 것이 가장 효율적이다.
"네가 요약한 걸 나중에 내가 주면,
네가 그 편향을 잘 일으킬 수 있게 요약해줘"
→ LLM이 자기 자신의 어텐션 특성을 알고 있으므로 최적 요약 가능
비용 구조: 요약은 1회성 비용 → 이후 사용자 질의마다 작은 토큰만 전송
4가지 요약 기법
| 기법 | 원리 | 장점 | 단점 |
|---|---|---|---|
| Stuff | 전체 문서를 한 번에 LLM에 전달 → 요약 | 단순 | 큰 모델 필요, 문서 크기 제한 |
| MapReduce | 페이지별 요약 → 요약의 요약 → ... 최종 1개 | 대규모 문서 처리 가능 | 서사 구조 손실 |
| MapRefine | 1장 요약 → 1장 요약+2장 함께 요약 → ... 순차적 | 서사 구조 보존 | 순차 처리로 느림 |
| ClusterMapRefine | RAPTOR식 클러스터링 + Refine | 계층적 요약 | 클러스터링 문제 그대로 상속 |
Refine의 정체
Refine은 영어 단어가 아니라 고유명사다. 이 동네(요약 기법)에서의 Refine이란: - 앞에서 요약한 결과를 이용해서 뒤의 데이터를 합쳐 다시 요약본을 만드는 것 - Chain of Density(CoD) 프롬프트가 Refine을 재귀적으로 활용
# MapRefine 패턴 구현
from langchain.chains.summarize import load_summarize_chain
# 서사 구조가 있는 문서 (1장→2장→3장 순서 중요)
chain = load_summarize_chain(
llm,
chain_type="refine", # 앞 요약을 바탕으로 뒤를 요약
refine_prompt=refine_prompt # 편향 최적화 지시 포함
)
⚠️ 최신 업데이트: LangChain의
ContextualCompressionRetriever, LlamaIndex의tree/refine synthesizer가 컨텍스트 압축의 표준 도구로 자리잡았다. 2025 기준 LlamaIndex는 retrieval accuracy 35% 향상을 달성했으며, LangChain은 LangGraph를 통해 복잡한 추론 워크플로우를 지원한다.
실무 적용
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
# LLM 기반 컨텍스트 압축 retriever
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vector_retriever
)
# → 검색 결과를 LLM이 질문에 관련된 부분만 추출하여 압축
핵심 체크포인트
- ✅ 대량 컨텍스트를 그대로 넣으면 어텐션 희석 → LLM 요약으로 압축 필수
- ✅ 서사 구조가 있는 문서는 MapRefine (순차 요약), 없으면 MapReduce (병렬 요약)
- ✅ 요약은 1회성 비용 — 이후 질의마다 작은 토큰만 전송하여 비용 절감
EP5. RAG와 프롬프트 — 어텐션 편향의 원리
강의 핵심 요약
프롬프트는 인간이 작성할 수 없는 프로그래밍 언어다. LLM만이 "이 단어 조합이 어떤 편향을 유도할지" 예측할 수 있다. 어텐션 편향에는 입력 편향(시스템 프롬프트)과 출력 편향(LLM 자체 생성 토큰)이 있으며, 토큰 수가 늘수록 어텐션 희석이 발생한다.
딥다이브
입력 편향 vs 출력 편향
입력 편향 (Input Bias)
─────────────────────
시스템 프롬프트 + 컨텍스트로 유도
→ "이 데이터를 기반으로 답변하세요"
출력 편향 (Output Bias)
─────────────────────
LLM이 생성한 토큰이 다음 토큰 생성에 영향
→ Chain of Thought(CoT)가 대표적 활용
→ "중간 과정을 떠들면서 마지막에 답변해봐"
디코더의 원리: 100개 토큰 → 101번째 생성 → 101개 토큰 → 102번째 생성 → ... - 내가 입력한 토큰 + LLM이 생성한 토큰 모두가 다음 토큰에 영향 - 리즈닝 모델의 원리가 바로 출력 편향 활용
어텐션 희석 (Attention Dilution)
10개 토큰 중 7번 토큰의 기여도: 1/10 = 10%
20,000개 토큰 중 7번 토큰의 기여도: 1/20,000 = 0.005%
→ 토큰이 많아질수록 개별 토큰의 영향력 급감
- 출력을 많이 시키면 초반 프롬프트가 점점 희석 → "뒤에 가면 기억도 못해"
- 대책: 토큰 임베딩 차원을 늘린 모델 사용
⚠️ 최신 업데이트: Adobe Research NoLiMa 벤치마크(2025)에서 12개 모델 중 11개가 32K 토큰에서 baseline 대비 50% 이하 성능을 보였다. GPT-4o도 99.3% → 69.7%로 하락. 2025 arXiv 연구는 "100% 완벽한 검색이 이루어져도 입력 길이 증가 시 13.9~85% 성능 저하"를 보고했다.
토큰 임베딩 차원과 희석의 관계
차원이 작은 모델 (예: 256d)
→ 토큰 희석 시 의미 보존 어려움
차원이 큰 모델 (예: 3072d, OpenAI text-embedding-3-large)
→ 어텐션 계산 효과가 많은 차원에 분포
→ 개별 토큰 영향 감소해도 차원별로는 충분한 기여
→ 어텐션 헤드를 더 많이 만들 수 있음
→ 긴 토큰에서도 맥락 유지 가능
컨텍스트 확장 모델의 활용
- 토큰 임베딩 차원은 작지만 입력 컨텍스트만 늘린 모델 존재
- 용도: 인코더처럼 활용 — "대규모로 받아서 요약해줘"
- 짧은 출력 생성 시 희석 전에 답변 완료 가능
- 인코더 대신 디코더를 쓰는 이유: 프롬프트 통제 가능
실무 적용
# 프롬프트 설계 시 어텐션 편향 활용 원칙
# 1. 중요한 지시는 프롬프트 앞쪽에 배치 (입력 편향 극대화)
# 2. 출력 길이를 제한하여 희석 방지
# 3. CoT로 출력 편향 활용
system_prompt = """[최우선 지시: JSON 형식으로만 답변] ← 앞쪽 배치
역할: {domain} 전문가
컨텍스트: {context}
제약: 3문장 이내로 답변하세요. ← 출력 제한으로 희석 방지
"""
# 프롬프트 사용 빈도별 설계 전략
# - 비정기적/특수 문제 → 느슨한 프롬프트 OK
# - 매일 스케줄 실행 → 일관된 결과 필요 → 정교한 프롬프트
# - 함수적 호출 (JSON 포맷 등) → 최고 수준의 프롬프트 기술 필요
핵심 체크포인트
- ✅ 프롬프트 = LLM만이 작성할 수 있는 프로그래밍 언어 (어텐션 편향 유도)
- ✅ 입력 편향(시스템 프롬프트) + 출력 편향(CoT) 조합으로 원하는 답 유도
- ✅ 어텐션 희석 대책 = 토큰 임베딩 차원이 큰 모델 + 출력 길이 제한
EP6. RAPTOR의 허실 — 계층적 클러스터링의 함정
강의 핵심 요약
RAPTOR는 청크 → 임베딩 → 차원 축소 → 클러스터링 → 요약 → 다시 임베딩의 계층 구조를 만든다. 이론적으로 추상적 질문은 상위 노드, 구체적 질문은 하위 리프에서 검색된다. 그러나 차원 축소의 시멘틱 파괴, 컨텍스트 혼합, 유사 시멘틱 문제로 실무에서 잘 작동하지 않는다.
딥다이브
RAPTOR 동작 흐름
청크들 → 임베딩 (756차원)
↓
차원 축소 (5차원 또는 2차원!) ← 여기서 시멘틱 파괴
↓
GMM 클러스터링 → 그룹 형성
↓
그룹 내 청크 모아서 LLM 요약
↓
요약문 다시 임베딩
↓
(반복) → 계층적 트리 구조 완성
3대 치명적 문제
1. 차원 축소에 의한 시멘틱 파괴
756차원 → 5차원 축소 시 시멘틱 정보 대부분 소실: - 차원이 많은 이유 = 다양한 시멘틱을 표현하기 위함 - 5차원으로 축소하면 코사인 유사도 비교 자체가 무의미
2. 컨텍스트 혼합 (Context Mixing)
시멘틱 구조가 비슷하지만 컨텍스트가 완전히 다른 청크들이 함께 클러스터링:
"임금이 죽었다" (한국 역사) ─┐
├→ 시멘틱 유사 → 같은 클러스터!
"천황이 죽었다" (일본 역사) ─┘
→ 컨텍스트는 완전히 다르지만 문장 구조가 같아서 임베딩이 유사
→ 함께 요약하면 의미 없는 결과
- 해결하려면 컨텍스트 격벽을 사람이 수동으로 설정해야 함 → 비현실적
3. 유사 시멘틱 문제 (Similar Semantics)
기업 데이터, 뉴스 기사 등에서 문장 구조(템플릿)는 같고 명사만 다른 경우: - 기사 기레기들의 포맷이 똑같아서 시멘틱 구조가 동일 - RDB 테이블을 문장으로 변환해도 구조 반복 - 임베딩 값이 거의 동일 → 클러스터링해도 무의미 → 요약도 무의미
⚠️ 최신 업데이트: Stanford CS224N 연구(2025)는 RAPTOR의 GMM 클러스터링 한계를 지적하며, Adaptive Graph Clustering(그래프 커뮤니티 탐지)을 대안으로 제시했다. HIRO(Hierarchical Information Retrieval Optimization)는 DFS 기반 재귀적 유사도 임계값 + 가지치기로 정보 과부하를 해결한다. PageIndex는 문서의 실제 페이지/섹션 계층 구조를 미러링하는 방식으로 RAPTOR의 임의적 클러스터링 문제를 회피한다.
실무 적용
# RAPTOR를 써도 되는 경우의 체크리스트
raptor_suitable = all([
"문서 주제가 단일하거나 매우 유사", # 세종대왕 문서 → OK
"컨텍스트가 상이한 내용이 혼재하지 않음", # 한국+일본 역사 → NG
"유사 시멘틱 반복 데이터가 아님", # RDB 테이블 변환 → NG
"클러스터링 결과가 유의미한지 검증 가능",
])
# RAPTOR 대안: 단순하지만 효과적인 접근
# 1. 메타데이터 기반 필터링 (문서 카테고리별 격벽)
# 2. 하이브리드 검색 (벡터 + BM25)
# 3. 2-stage 리랭킹 (크로스 인코더 + LLM)
핵심 체크포인트
- ✅ RAPTOR의 756차원→5차원 축소는 시멘틱을 파괴 — 클러스터링 자체가 무의미해질 수 있음
- ✅ 컨텍스트가 다른 청크가 시멘틱 구조 유사로 함께 클러스터링되는 문제
- ✅ RAPTOR 논문의 데이터셋은 RAPTOR에 맞게 정교하게 구성된 것 — 범용 데이터에는 주의
EP7. RAG 시스템 평가하기
강의 핵심 요약
RAG 평가의 핵심 4대 지표: 정확성, 관련성, 이행성, 안정성. 보조 지표로 컨텍스트 일관성, 논리적 일관성, 간결성, 창의성이 있다. 평가 자체도 LLM으로 수행하며(LLM-as-Judge), 테스트셋도 LLM이 생성한다.
딥다이브
4대 핵심 평가 지표
| 지표 | 설명 | 난이도 |
|---|---|---|
| 정확성 (Accuracy) | 올바르고 정확한 답변인가 | 매우 어려움 — "독도는 누구 땅?" 같은 문제 |
| 관련성 (Relevance) | 질문 의도에 부합하는가 | 상대적으로 측정 용이 |
| 이행성 (Compliance) | 지시한 대로 수행하는가 | 양날의 검 — 이행성 높음 = 시키지 않은 건 안 함 |
| 안정성 (Safety) | 위험한 답변을 하지 않는가 | 기밀 누출, 인명 살상 정보 등 |
보조 지표의 상호 관계
이행성 ←──→ 컨텍스트 일관성 (같이 흐름)
│ │
└──→ 논리적 일관성 (자기 모순성 방지)
이행성 높음 = 멍청함 (시킨 것만 함)
이행성 낮음 = 지멋대로 (컨텍스트 일관성도 나빠짐)
간결성 ←──→ 창의성 (상충 관계)
저파라미터 모델 → 확률 분포 뻔함 → 창의성 낮음
LLM-as-Judge 평가 방식
# LLM으로 RAG 품질 평가
evaluation_prompt = """다음 질문-답변 쌍을 평가하세요.
질문: {question}
정답(기대): {expected_answer}
실제 답변: {actual_answer}
참조 컨텍스트: {context}
평가 항목 (각 1~5점):
1. 정확성: 사실적으로 올바른가?
2. 관련성: 질문 의도에 부합하는가?
3. 이행성: 지시사항을 준수했는가?
4. 안전성: 위험한 내용이 없는가?
JSON으로 점수와 근거를 반환하세요."""
디퓨전 모델 — 토큰 생성의 대안
- GPT 방식: 토큰을 하나씩 순차 생성
- 디퓨전 모델: 전체 답변을 "뿌옇게 → 선명하게" 확산 역과정으로 생성
- 잉크 비유: 물에 잉크 한 방울 → 파란물이 됨 → 이 파란물에서 원래 잉크를 역추적하는 학습
⚠️ 최신 업데이트: RAGAS 프레임워크가 RAG 평가의 사실상 표준으로 자리잡았다. 핵심 메트릭 — Context Precision(검색된 청크 중 실제 활용 비율), Context Recall(필요 정보의 검색 커버리지), Faithfulness(답변이 컨텍스트에 충실한지). RAGAS는 LangChain, LlamaIndex, Haystack 등 주요 프레임워크와 통합을 지원한다.
실무 적용
# RAGAS를 이용한 RAG 시스템 평가
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
result = evaluate(
dataset=eval_dataset,
metrics=[faithfulness, answer_relevancy,
context_precision, context_recall],
)
print(result) # 각 메트릭별 0~1 점수
# LLM으로 테스트셋 생성
test_gen_prompt = """다음 청크들을 기반으로 QA 테스트셋을 만들어주세요.
청크들: {chunks}
각 질문에 대해:
1. 질문 (자연스러운 한국어)
2. 기대 답변
3. 관련 청크 ID 목록
4. 난이도 (easy/medium/hard)
JSON 배열로 반환하세요."""
핵심 체크포인트
- ✅ 핵심 4대 지표: 정확성·관련성·이행성·안정성 — 거의 모든 평가에 공통
- ✅ 이행성은 양날의 검 — 높으면 시킨 것만 하고, 낮으면 컨텍스트 일관성도 무너짐
- ✅ 평가도 LLM, 테스트셋도 LLM이 생성 — 사람이 만들 수 없는 규모
EP8. RAG 시스템 튜닝하기
강의 핵심 요약
RAG 튜닝은 4단계 파이프라인: 청크 튜닝 → 벡터 검색 튜닝 → 비임베딩 요소 강화 → 부분 요소 교체. 가장 영향이 크지만 부담도 큰 것이 체인 변경과 임베딩 모델 변경이고, 가장 현실적인 것이 비임베딩 요소 강화(BM25 병행, 메타데이터 등)다. 청크 튜닝이 가장 기본이자 가장 많은 기업이 실패하는 지점이다.
딥다이브
RAG 튜닝 4단계
1. 청크 튜닝 ← 가장 기본, 여기서 대부분 실패
↓
2. 벡터 검색 튜닝 ← 임베딩 모델 교체 (비용 큼)
↓
3. 비임베딩 요소 강화 ← BM25 병행, 메타데이터 (현실적)
↓
4. 부분 요소 교체 ← 리랭커 교체 등 (국소적 변경)
청크 튜닝 — 대부분이 실패하는 이유
스플리터 선택이 핵심: 대부분 기업이 단순 글자수 기반 스플리터를 사용하여 실패
문제: "앞 문장 중간 ~ 뒷 문장 앞부분"으로 잘림
→ 임베딩이 제대로 될 리 없음
→ 뒤에 리랭커를 붙여도 소용없음 (쓰레기 in = 쓰레기 out)
스플리터 발전 순서: 1. 글자수 기반 → 단어 깨짐 2. 공백 기반 → 문장 깨짐 3. 정규식 기반 → 유연성 부족 4. 형태소 분석기 → 문장 정확 인식 5. LLM 토크나이저 → 가장 정확
LLM을 이용한 청크 품질 평가 (3가지 기준)
| 기준 | 설명 |
|---|---|
| 임베딩 적합성 | 이 청크를 임베딩했을 때 유사도 검색이 잘 맞을 것인가 |
| 시멘틱 독립성 | 청크가 독립된 의미를 갖고 있는가 (날씨+샐러드 혼재 → NG) |
| 시멘틱 완전성 | 원문의 정보가 청킹 과정에서 누락되지 않았는가 |
# LLM을 이용한 청크 품질 평가
chunk_eval_prompt = """원문 페이지와 이로부터 생성된 청크들을 비교하세요.
원문: {original_page}
청크들: {chunks}
평가 기준:
1. 임베딩 적합성: 각 청크를 임베딩하면 유사도 검색이 잘 될까?
2. 시멘틱 독립성: 각 청크가 하나의 독립된 주제를 다루고 있는가?
3. 시멘틱 완전성: 원문 정보가 청킹 과정에서 누락되지 않았는가?
각 기준별 OK/NG와 근거를 반환하세요."""
벡터 검색 튜닝 — LLM으로 테스트셋 자동 생성
# LLM에게 청크 기반 QA 테스트셋 생성 의뢰
# 큰 모델: 청크 많이 + 질문 많이 = 한 번에
# 작은 모델: 청크 3개씩 + 질문 2개씩 = 여러 번 반복
test_gen_prompt = """아래 500개 청크를 보고:
1. 검증용 질문 200개를 만들어주세요
2. 각 질문에 관련된 청크 ID를 매핑해주세요
3. 예상 유사도 점수도 포함해주세요"""
# → 이 테스트셋으로 벡터 DB 검색 결과와 비교
# → 불일치 항목에서 임베딩 모델 교체 여부 판단
튜닝 영향도 vs 부담
| 튜닝 항목 | 영향도 | 부담도 | 비고 |
|---|---|---|---|
| RAG 체인 변경 | 최대 | 최대 | 전체 아키텍처 변경 |
| 임베딩 모델 변경 | 대 | 대 | 전체 데이터 재임베딩 필요 |
| 비임베딩 강화 | 중 | 소 | BM25, 메타데이터 추가 |
| 부분 요소 교체 | 소~중 | 소 | 리랭커 교체 등 |
⚠️ 최신 업데이트: 2026 벤치마크에 따르면 RecursiveCharacterTextSplitter (400~512 토큰, 10~20% overlap)가 여전히 시작점으로 권장된다. NAACL 2025는 "200-word 고정 청크가 시멘틱 청킹과 동등하거나 우수"하다고 보고했다. 2026의 late chunking, contextual retrieval이 overlap 조정보다 큰 성능 향상을 보이는 새로운 트렌드다.
실무 적용
# 실무 청크 튜닝 파이프라인
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 1단계: 시작점 — 400~512 토큰, 10~20% overlap
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", ".", " "]
)
# 2단계: LLM으로 청크 품질 검증
# 3단계: 스플리터 파라미터 조정 또는 스플리터 교체
# 4단계: 벡터 검색 테스트셋으로 end-to-end 검증
핵심 체크포인트
- ✅ 대부분 기업이 청크 스플리터에서 실패 — 글자수 기반 스플리팅은 임베딩을 망가뜨림
- ✅ 청크 품질 검증 3기준: 임베딩 적합성·시멘틱 독립성·시멘틱 완전성 (LLM으로 자동 평가)
- ✅ 비임베딩 요소 강화(BM25 병행, 메타데이터)가 가장 현실적인 품질 개선 방법
부록 A: 용어 사전
| 용어 | 설명 |
|---|---|
| 어텐션 편향 (Attention Bias) | 입력 토큰의 구성에 따라 어텐션 계산 결과가 달라지는 현상 |
| 입력 편향 (Input Bias) | 시스템 프롬프트·컨텍스트로 유도하는 어텐션 편향 |
| 출력 편향 (Output Bias) | LLM이 생성한 토큰이 후속 토큰 생성에 영향을 주는 편향 |
| 어텐션 희석 (Attention Dilution) | 토큰 수 증가 → 개별 토큰의 어텐션 기여도 감소 |
| 크로스 인코더 | 쿼리+문서 쌍을 BERT에 입력하여 유사도 점수를 출력하도록 학습한 모델/방법 |
| Refine | (고유명사) 앞 요약을 바탕으로 뒤 데이터를 합쳐 재요약하는 기법 |
| RAPTOR | Recursive Abstractive Processing for Tree-Organized Retrieval |
| MapReduce | 청크별 병렬 요약 → 요약의 요약으로 리듀스 |
| MapRefine | 순차적으로 앞 요약+뒷 데이터를 합쳐 재요약 (서사 구조 보존) |
| BM25 | 형태소 분석 + TF-IDF 기반 키워드 매칭 알고리즘 |
| Stuff | 전체 문서를 한 번에 LLM에 전달하는 요약 방식 |
| CoT (Chain of Thought) | 출력 편향을 활용하여 중간 추론을 생성하게 하는 기법 |
| 컨텍스트 혼합 | RAPTOR에서 시멘틱은 유사하나 컨텍스트가 다른 청크가 함께 클러스터링되는 문제 |
| 유사 시멘틱 | 문장 구조(템플릿)가 동일하여 임베딩이 같게 나오는 문제 |
| LLM-as-Judge | LLM을 평가자로 활용하는 방식 |
| RAGAS | Retrieval Augmented Generation Assessment 프레임워크 |
부록 B: 비교표
B-1. 리랭커 방식 비교
| 항목 | 크로스 인코더 | LLM Pointwise | LLM Listwise | 2-Stage 하이브리드 |
|---|---|---|---|---|
| 호출 횟수 | N회 | N회 | 1회 | 크로스N + LLM 1 |
| 속도 | 5~10ms | 200ms×N | 200~500ms | ~510ms |
| 프롬프트 통제 | 불가 | 가능 | 가능 | 가능 (2차) |
| 정확도 (상대) | 95% | 90% | 100% (기준) | 최고 |
| 비용/1K쿼리 | ~$0.50 | 높음 | $5~10 | ~$6 |
| 추천 용도 | 1차 필터 | 단건 검증 | 최종 정렬 | 프로덕션 |
B-2. 요약 기법 비교
| 기법 | 서사 보존 | 병렬 처리 | 정보 손실 | 적합 문서 |
|---|---|---|---|---|
| Stuff | N/A | N/A | 최소 | 짧은 문서 |
| MapReduce | 낮음 | 가능 | 중간 | 대규모·독립 섹션 |
| MapRefine | 높음 | 불가 | 낮음 | 순서 의존 문서 |
| ClusterMapRefine | 중간 | 부분 | 높음 (클러스터링 실패 시) | 주제 단일 문서 |
B-3. RAG 튜닝 영향도 매트릭스
| 튜닝 대상 | 영향도 | 비용 | 리스크 | 권장 순서 |
|---|---|---|---|---|
| 청크 스플리터 | 최고 | 낮음 | 중간 | 1순위 |
| 비임베딩 강화 | 중간 | 낮음 | 낮음 | 2순위 |
| 리랭커 교체 | 중간 | 중간 | 낮음 | 3순위 |
| 임베딩 모델 | 높음 | 높음 | 높음 (재인덱싱) | 4순위 |
| RAG 체인 | 최고 | 최고 | 최고 | 최후 수단 |
부록 C: 추천 참고 자료 & 링크
공식 문서·프레임워크
- LangChain — ContextualCompressionRetriever
- LlamaIndex — Tree/Refine Synthesizer
- RAGAS — RAG 평가 프레임워크
- Sentence Transformers — Cross-Encoder
임베딩 모델
- OpenAI text-embedding-3-large (3072d)
- Google gemini-embedding-001 (MRL 적용)
- Cohere embed-v4 (MTEB 1위)
- EmbeddingGemma (308M, 온디바이스)
리랭커
논문·연구
- RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval (2024)
- HIRO: Hierarchical Information Retrieval Optimization (2024)
- Enhancing RAPTOR with Semantic Chunking and Adaptive Graph Clustering (2025)
- NoLiMa: Long-context LLM Benchmark (2025)
청크 전략
클릭하거나 Space를 눌러 뒤집기